﻿#include "stdafx.h"
#include "RoutineAction.h"
#include "DefInfo/def_spell.h"
#include "DefInfo/GameInfo.h"
#include "DefInfo/Team_Raid_Info.h"
#include "boost/format.hpp"
#include "PressKeyUtil.h"
#include "IRoutine.h"



RoutineAction::RoutineAction()
{
}


RoutineAction::~RoutineAction()
{
}

bool RoutineAction::PushSequence(std::string order, SpellID spell, fun_action_condition fun)
{
	action_order_condition aoc;
	aoc.fun = fun;
	aoc.order = order;
	aoc.spell = spell;
	vec_funs_.push_back(aoc);
	return true;
}

bool RoutineAction::PushHealSequence(std::string order, SpellID spell, fun_action_condition fun)
{
	action_order_condition aoc;
	aoc.fun = fun;
	aoc.order = order;
	aoc.spell = spell;
	vec_heal_self_funs_.push_back(aoc);
	return true;
}

void RoutineAction::DoAction()
{
	if (vec_funs_.size() > 0)
	{
		for (auto& aoc : vec_funs_)
		{
			if (!SpellReady(aoc.spell))
			{
				continue;
			}
			if (aoc.fun(aoc.spell))
			{
				if (Cast(aoc.spell))
				{
					break;
				}
			}
		}
	}
}

void RoutineAction::DoHealSelfAction()
{
	if (vec_heal_self_funs_.size() > 0)
	{
		for (auto& aoc : vec_heal_self_funs_)
		{
			if (!SpellReady(aoc.spell))
			{
				continue;
			}
			if (aoc.fun(aoc.spell))
			{
				if (Cast(aoc.spell))
				{
					break;
				}
			}
		}
	}
}

using press_keys = std::vector<unsigned char>;
using map_target_keys = std::map<std::string, press_keys>;
map_target_keys map_target = {
	{"player", {VK_F1}},
};


void RoutineAction::Init()
{
	for (int i = 1; i <= 4; i++)
	{
		boost::format fmt("party%d");
		fmt%i;
		std::string name = fmt.str();
		auto& keys = map_target[name];
		keys.push_back(VK_F1 + i);
	}
	for (int i = 1; i <= 40; i++)
	{
		boost::format fmt("raid%d");
		fmt%i;
		std::string name = fmt.str();
		auto& keys = map_target[name];
		int key_index = (i - 1) % 12 + 1;
		if (i >= 1 && i <= 12)
		{
			keys.push_back(VK_LSHIFT);
			keys.push_back(VK_F1 + key_index - 1);
		}
		else if (i >= 13 && i <= 24)
		{
			keys.push_back(VK_LCONTROL);
			keys.push_back(VK_LSHIFT);
			keys.push_back(VK_F1 + key_index - 1);
		}
		else if (i >= 25 && i <= 36)
		{
			keys.push_back(VK_LCONTROL);
			keys.push_back(VK_F1 + key_index - 1);
		}
		else if (i >= 37 && i <= 48)
		{
			keys.push_back(VK_LMENU);
			keys.push_back(VK_LSHIFT);
			keys.push_back(VK_F1 + key_index - 1);
		}
	}
}

RoutineAction::action_order_condition& RoutineAction::GetLastActionOrderCondition()
{
	auto& back = vec_funs_.back();
	return back;
}

RoutineAction::action_order_condition& RoutineAction::GetActionOrderByOrder(std::string order)
{
	for (auto& condition : vec_funs_ )
	{
		if (condition.order == order)
		{
			return condition;
		}
	}
	action_order_condition action;
	return action;
}

void RoutineAction::SetConRoSpellID(unsigned int SpellID)
{
	if (ConRoSpellID!=NULL)
	{
		*ConRoSpellID = SpellID;
	}
}


void RoutineAction::SetConRoSpellPoint(unsigned int* point)
{
	ConRoSpellID = point;
}

bool RoutineAction::Cast(SpellID spell)
{
	if (!PressKeyUtil::inst().SendLock())
	{
		GameInfo::inst().prev().Cast(spell);
	}
	PressKeyUtil::inst().SendKeyBySpellID(spell);
	return true;
}

bool RoutineAction::SpellReady(SpellID spell)
{
	if (GameInfo::inst().CheckSpellCanUse(spell))
	{
		return true;
	}
	return false;
}

unsigned int* RoutineAction::ConRoSpellID = NULL;

std::string RoutineAction::ChooseHealTarget(VecLostHp& vec_hps)
{
	std::string target;
	int max_player_lost = 0;

	if ((GameInfo::inst().IsInRaid() || GameInfo::inst().IsInParty()) && GameInfo::inst().GetTeam_Raid_Count() > 0)
	{
		for (int i = 0; i < GameInfo::inst().GetTeam_Raid_Count(); i++)
		{
			auto& item = GameInfo::inst().GetTeam_Raid_Item(i);
			int expect_heal = item.GetExpectHealValue();
			int lost_hp = item.player_hp_max - item.player_hp;
			lost_hp = lost_hp - expect_heal;
			double distance = item.GetDistance();
			if (item.IsDeadOrGhost())
			{
				if (GameInfo::inst().PlayerInBattle())
				{
					if (GameInfo::inst().GetActionCDBySpellId(Rebirth) != 0)
					{
						lost_hp = 0;
					}
				}
				else
				{
					if (GameInfo::inst().GetActionCDBySpellId(Revive) != 0)
					{
						lost_hp = 0;
					}
				}
			}
			if (lost_hp > 0 && distance <= 42.0f)
			{
				if (lost_hp > max_player_lost)
				{
					max_player_lost = lost_hp;
					target = item.GetName();
				}

				vec_hps.push_back({ lost_hp , distance });
			}
		}
	}
	else {
		// 查看自己和目标是否血不足
		int self_lost_hp = GameInfo::inst().GetPlayer().player_hp_max - GameInfo::inst().GetPlayer().player_hp;
		int expect_heal = GameInfo::inst().GetPlayerExpectHealValue();
		self_lost_hp = self_lost_hp - expect_heal;
		if (self_lost_hp > 0)
		{
			target = "player";
			vec_hps.push_back({ self_lost_hp, GameInfo::inst().GetPlayer().GetDistance() });
		}
		if (!GameInfo::inst().TargetIsEnemy() && !GameInfo::inst().GetIsPlayerIsTarget())
		{
			int target_lost_hp = GameInfo::inst().GetTargetHpMax() - GameInfo::inst().GetTargetHp();
			expect_heal = GameInfo::inst().GetTargetExpectHealValue();
			target_lost_hp = target_lost_hp - expect_heal;

			if (GameInfo::inst().GetTarget().IsDeadOrGhost())
			{
				if (GameInfo::inst().PlayerInBattle())
				{
					if (!GameInfo::inst().CheckSpellCanUse(Rebirth))
					{
						target_lost_hp = 0;
					}
				}
				else
				{
					if (!GameInfo::inst().CheckSpellCanUse(Revive))
					{
						target_lost_hp = 0;
					}
				}
			}
			double distance = GameInfo::inst().GetTarget().GetDistance();
			if (target_lost_hp > 0 && distance < 42.0f)
			{
				if (target_lost_hp > self_lost_hp)
				{
					target = "target";
				}

				vec_hps.push_back({ target_lost_hp , distance });
			}
		}
	}
	return target;
}

bool RoutineAction::ChangeTarget(std::string heal_target)
{
	auto it = map_target.find(heal_target);
	if (it != map_target.end())
	{
		press_keys& keys = it->second;
		PressKeyUtil::inst().SendKey(keys, 0);
		return true;
	}
	return false;
}

bool IRoutine::SatisfySpellCondition(std::string name, Team_Raid_Info& target)
{
	return GameInfo::inst().SatisfySpellCondition(name, spec_id, target);
}